package com.xxl.sso.server.core.util;

import java.text.SimpleDateFormat;
import java.util.Date;

public class UniqueSeqUtil {
    private static volatile int seq = 0;
    private static volatile long currentTimeMillis;

    public static class UniqueId {
        private final long currentTimeMillis;
        private final String id;
        private final String compensate;

        public UniqueId(long currentTimeMillis, String id, String compensate) {
            this.currentTimeMillis = currentTimeMillis;
            this.id = id;
            this.compensate = compensate;
        }

        /**
         * 生成该id时候的时间戳
         */
        public long getCurrentTimeMillis() {
            return currentTimeMillis;
        }

        /**
         * 唯一ID
         */
        public String getId() {
            return id;
        }

        /**
         * 补全的位，该时间戳的第几个
         */
        public String getCompensate() {
            return compensate;
        }
    }

    /**
     * 生成一个唯一的订单序列,长度为 yyyyMMddHHmmssSSS + compensateI
     *
     * @param compensateI 4 代表长度加4位 ，支持每毫秒4位的并发
     * @return
     */
    public final static synchronized UniqueId uniqueId(int compensateI) {
        final long ctm = System.currentTimeMillis();
        if (currentTimeMillis != ctm) {
            seq = 0;
            currentTimeMillis = ctm;
        }
        String compensate = "";// 补零
        String sqlStr = String.valueOf(++seq);
        int length = sqlStr.length();
        for (int i = 0; i < compensateI - length; i++) {
            compensate += "0";
        }
        String currentTimeStr = (new SimpleDateFormat("yyyyMMddHHmmssSSS")).format(new Date(ctm));
        String id = currentTimeStr + compensate + sqlStr;
        return new UniqueId(ctm, id, compensate);
    }


    private static volatile long currentTimeMillis1;
    /**
     * 生成一个唯一序列yyyyMMddHHmmssSSS，延迟一毫秒生成，多线程调用那么串行
     */
    public static String yyyyMMddHHmmssSSS() {
        long ctm;
        synchronized (UniqueSeqUtil.class) {
            while (true) {
                ctm = System.currentTimeMillis();
                if (currentTimeMillis1 != ctm) {
                    currentTimeMillis1 = ctm;
                    break;
                }
            }
        }
        String currentTimeStr = (new SimpleDateFormat("yyyyMMddHHmmssSSS")).format(new Date(ctm));
        return currentTimeStr;
    }

}
